﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using DALEntities;

namespace ServerPlatform.DataProvider
{
    public class LookupItem
    {
        public object value;
        public object valueList;
    }

    public class LookupHelper
    {
        private IList data;
        private string keyField;
        private string valueField;
        private DataType type;

        internal Dictionary<object, LookupItem> cache = null;

        public LookupHelper(IList data, string keyField, string valueField)
        {
            this.data = data;
            this.keyField = keyField;
            this.valueField = valueField;
            if (data.Count > 0)
            {
                object keyValueInList = DataProviderFramework.Eval(data[0], keyField);
                type = GetKnownType(keyValueInList);
            }
            else type = DataType.Unknown;
            
        }

        private DataType GetKnownType(object keyValueInList)
        {
            if (keyValueInList == null)
                return DataType.Unknown;
            else
            {
                Type t = keyValueInList.GetType();
                if (t == typeof(int) || t == typeof(short) || t == typeof(uint) || t == typeof(Int16) || t == typeof(ushort))
                    return DataType.Integer;
                else if (t == typeof(decimal))
                    return DataType.Decimal;
                else if (t == typeof(double))
                    return DataType.Double;
                else if (t == typeof(DateTime))
                    return DataType.DateTime;
                else if (t == typeof(Int64))
                    return DataType.Int64;
                else if (t == typeof(string))
                    return DataType.String;
                else return DataType.Unknown;
            }
        }

        private object ConvertTo(object val)
        {
            
            switch (type)
            {
                case DataType.Blob:
                case DataType.Unknown:
                case DataType.Spatial: return val;
                case DataType.DateTime: return Convert.ToDateTime(val);
                case DataType.Decimal: return Convert.ToDecimal(val);
                case DataType.Double: return Convert.ToDouble(val);
                case DataType.Int64: return Convert.ToInt64(val);
                case DataType.Integer: return Convert.ToInt32(val);
                case DataType.String: return Convert.ToString(val);
                default: return val;
            }
        }

        public Dictionary<object, LookupItem> Cache
        {
            get
            {
                if (cache == null)
                    Lookup(null);
                return cache;
            }
        }

        public object Lookup(object keyValue)
        {
            if (cache != null)
            {
                try
                {
                    return cache[ConvertTo(keyValue)].valueList;
                }
                catch
                {
                    return null;
                }                
            }
            else
            {
                object result = null;
                cache = new Dictionary<object, LookupItem>(data.Count);
                foreach (var item in data)
                {
                    object keyValueInList = DataProviderFramework.Eval(item, keyField);
                    cache.Add(keyValueInList, new LookupItem() { valueList = item, 
                        value = DataProviderFramework.Eval(item, valueField)});
                    if (keyValueInList != null && keyValue != null && ConvertTo(keyValueInList).Equals(ConvertTo(keyValue)))
                        result = item;
                }
                return result;
            }
        }
    }
}
